﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include "BurnDlgMcu.h"
#include <QMessageBox>
#include <QFileInfo>
#include <QCompleter>
#include <QFileDialog>
#include <QListView>
#include "DataConvertor.h"
#include "BurnToolCommon/Global.h"
#include "BurnCtrl/BurnCtrlMcu.h"
#include "BurnCtrl/BurnCtrlFaction.h"
#include "../platform/Securec/securec.h"

namespace BurnDlg {

namespace  {
    const int SYSTEM_NUM_16 = 0x10;
    const int SYSTEM_NUM_10 = 0x0A;
    const int COLUMN_WIDTH_SIZE_20 = 20;
    const int COLUMN_WIDTH_SIZE_100 = 100;
    const int COLUMN_WIDTH_SIZE_200 = 200;
    const int COLUMN_MINIMUM_HEIGHT_SIZE_192 = 192;
    const int I2C_DEVICE_ADDRESS = 0x14;
    const int KB_UNIT = 1024;
    const int ERASE_START_ADDRESS_BASE_BIT = 1024;
    const int LAYOUT_ROW = 1;
    const int LAYOUT_COLUMN = 3;
    const int LAYOUT_ROW_SPAN = 1;
    const int LAYOUT_COLUMN_SPAN = 3;
    const int RANGE_MINIMUM = 0;
    const int RANGE_MAXIMUM = 100;
    const char* const CONFIG_PATH = "\\config_mcu\\config\\config.ini";
}

BurnDlgMcu::BurnDlgMcu(ChipType chipType, QWidget *pParent)
    : BurnDlg(pParent),
      ui(new Ui::BurnDlgMcu),
      configIniRead(nullptr),
      chipIniRead(nullptr),
      loaderPath(""),
      targetFileJTAG(""),
      targetFileSWD(""),
      targetFileInfoJTAG(""),
      targetFileInfoSWD(""),
      chipIDAddress(0),
      chipIDSize(0),
      hexToBinPath(""),
      sramStartAddress(0),
      sramEndAddress(0),
      targetAddress(0),
      mainStartAddress(0),
      mainSize(0),
      uploadStartAddress(0),
      uploadSize(0),
      infoStartAddress(0),
      systemNum(0),
      actAbout(new QAction(stringClass.GetAbout())),
      actChangeChip(new QAction(stringClass.GetChangeChip())),
      isEnter(false),
      paramDlg(new ParamSettingDlg()),
      isInfoPart(false),
      eraseBaseNum(1),
      multipleBurnDlg(nullptr)
{
    this->chipType = chipType;
    ui->setupUi(this);
    binModel = new BinFileModel();
    BurnDlgMcu::InitBurnCtrl();
    Init();
    InitTableView();
    if (burnCtrl != nullptr) {
        burnCtrl->StartWiteMonitoring();
    }
}

BurnDlgMcu::~BurnDlgMcu()
{
    delete ui;
    ui = nullptr;
}

/* Interface Attribute Initialization */
void BurnDlgMcu::Init()
{
    ui->menuHelp->addAction(actAbout);
    ui->menuOption->addAction(actChangeChip);
    ui->menuSetting->addMenu(menuWifiLanguage);
    QHBoxLayout *layout = new QHBoxLayout();
    layout->addWidget(ui->pbExport);
    layout->addWidget(ui->pbErase);
    layout->addWidget(ui->pbEraseAll);

    ui->glExportErase->addLayout(layout, LAYOUT_ROW, LAYOUT_COLUMN, LAYOUT_ROW_SPAN, LAYOUT_COLUMN_SPAN);
    ui->textEditReceive->setReadOnly(true); /* The log box is read-only. */
    ui->progressBarReceive->setRange(RANGE_MINIMUM, RANGE_MAXIMUM);
    ui->progressBarReceive->setValue(0);

    if (!ReadConfigIni()) {
        QString absConfigPath = Global::GetAppConfigPath() + CONFIG_PATH;
        QMessageBox::information(nullptr, stringClass.GetInformation(),
                                 stringClass.GetNotReadPermissionTips().arg(absConfigPath));
        return;
    }
    IniChipModel();
    InitConnect();
    SlotChipModeCurrentIndexChanged("");
    SlotCbnSetfocusComboCom();
}

void BurnDlgMcu::InitConnect()
{
    if (ui == nullptr || actAbout == nullptr || actChangeChip == nullptr) {
        return;
    }
    connect(actAbout, &QAction::triggered, this, &BurnDlgMcu::SlotShowAbout);
    connect(actChangeChip, &QAction::triggered, this, &BurnDlgMcu::SlotShowChangeChip);
    connect(ui->cbChipModel, SIGNAL(currentIndexChanged(const QString &)),
            this, SLOT(SlotChipModeCurrentIndexChanged(const QString &)));
    connect(ui->cbTransferMethod, SIGNAL(currentIndexChanged(const QString &)),
            this, SLOT(SlotTransferMethodCurrentIndexChanged(const QString &)));
    connect(ui->cbCom, &ComboBoxCom::Clicked, this, &BurnDlgMcu::SlotCbnSetfocusComboCom);
    connect(ui->btnSelectFile, &QPushButton::clicked, this, &BurnDlgMcu::SlotBnClickedButtonSelectfile);
    connect(ui->pbConnect, &QPushButton::clicked, this, &BurnDlgMcu::SlotConnectBtnClicked);
    connect(ui->btnStartBurn, &QPushButton::clicked, this,  &BurnDlgMcu::SlotBnClickedButtonStartburn);
    connect(ui->pbSelectTarget, &QPushButton::clicked, this, &BurnDlgMcu::SlotBnClickedSelectTarget);
    connect(ui->pbExport, &QPushButton::clicked, this, &BurnDlgMcu::SlotBnClickedExport);
    connect(ui->pbErase, &QPushButton::clicked, this, &BurnDlgMcu::SlotBnClickedErase);
    connect(ui->pbEraseAll, &QPushButton::clicked, this, &BurnDlgMcu::SlotEraseAllMemory);
    connect(ui->pbParamSetting, &QPushButton::clicked, this, &BurnDlgMcu::SlotParamSetting);
    connect(ui->pbMultipleBurn, &QPushButton::clicked, this, &BurnDlgMcu::SlotBnClickedMultipleBurn);
    connect(paramDlg, &ParamSettingDlg::SignalSetLog, this, &BurnDlgMcu::SlotShowLog);
    if (burnCtrl == nullptr) {
        return;
    }
    connect(burnCtrl, &BurnCtrl::SignalSetLog, this, &BurnDlgMcu::SlotShowLog);
    connect(burnCtrl, &BurnCtrl::SignalSetConnectStatus, this, &BurnDlgMcu::SlotSetConnectStatus);
    connect(burnCtrl, &BurnCtrl::SignalSetTips, this, &BurnDlgMcu::SlotSetTips);
    connect(burnCtrl, &BurnCtrl::SignalChangeChipModeByChipId, this, &BurnDlgMcu::SlotChangeChipModeByChipId);
    connect(burnCtrl, &BurnCtrl::SignalSetProgressValue, this, &BurnDlgMcu::SlotSetProgress);
    connect(burnCtrl, &BurnCtrl::SignalInsertPlainText, this, &BurnDlgMcu::SlotInsertPlainText);
    connect(burnCtrl, &BurnCtrl::SignalBurnFileFinish, this, &BurnDlgMcu::SlotBurnFileFinish);
    connect(burnCtrl, &BurnCtrl::SignalBurnFileFailed, this, &BurnDlgMcu::SlotBurnFileFailed);
    connect(burnCtrl, &BurnCtrl::SignalExportSuccess, this, &BurnDlgMcu::SlotExportFinish);
    connect(burnCtrl, &BurnCtrl::SignalExportfail, this, &BurnDlgMcu::SlotExportFail);
    connect(this->burnCtrl, &BurnCtrl::SignalSetParameterInfoList, paramDlg,
            &ParamSettingDlg::SlotSetParameterInfoList, Qt::DirectConnection);
    connect(paramDlg, &ParamSettingDlg::SignalGetParameter, this, &BurnDlgMcu::SlotGetParameter);
    connect(paramDlg, &ParamSettingDlg::SignalSetParameter, this, &BurnDlgMcu::SlotSetParameter);
}

/* Read the config.ini file to obtain the handle. */
bool BurnDlgMcu::ReadConfigIni()
{
    QString absConfigPath = Global::GetAppConfigPath() + CONFIG_PATH;
    if (!IsFileExist(absConfigPath)) {
        return false;
    }
    if (!IniReadMemory(configIniRead, absConfigPath)) {
        return false;
    }
    return true;
}

bool BurnDlgMcu::IsFileExist(const QString &fileName) const
{
    QFileInfo fileInfo(fileName);
    return fileInfo.isFile();
}

void BurnDlgMcu::IniChipModel()
{
    ui->cbChipModel->clear();
    ui->cbChipModel->setEditable(true);
    QCompleter *pCompleter = new (std::nothrow)QCompleter(ui->cbChipModel->model());
    if (pCompleter == nullptr) {
        return;
    }
    pCompleter->setFilterMode(Qt::MatchContains);
    ui->cbChipModel->setCompleter(pCompleter);

    systemNum = SYSTEM_NUM_16;
    ShowQComboBox(configIniRead, "chipName", ui->cbChipModel, systemNum);
}

void BurnDlgMcu::ShowQComboBox(QSettings *fd, QString group, QComboBox *qBox, int baseSystem) const
{
    if (fd == nullptr || qBox == nullptr) {
        return;
    }
    fd->beginGroup(group);
    QStringList keys = fd->childKeys();
    fd->endGroup();
    for (QStringList::iterator item = keys.begin(); item != keys.end(); ++item) {
        QString key = *item;
        QString value = fd->value("/" + group + "/" + key, "").toString();
        if (key.contains("-", Qt::CaseSensitive)) {
            key = key.mid(key.indexOf("-") + 1);
        }
        qBox->addItem(key, value.toInt(Q_NULLPTR, baseSystem));
    }
}

void BurnDlgMcu::SlotChipModeCurrentIndexChanged(const QString &arg1)
{
    Q_UNUSED(arg1);
    if (IsFirstSeriesChip(GetChipMode())) {
        ui->cbRunDirectly->setChecked(true);
        ui->cbRunDirectly->setEnabled(false);
    } else {
        ui->cbRunDirectly->setEnabled(true);
    }

    if (!ReadChipConfigIni()) {
        ChipModeChangeInit();
        return;
    }

    ChipModeChangeInit();
}

bool BurnDlgMcu::IsFirstSeriesChip(int chipMode) const
{
    if (chipMode == CHIP_TYPE_MCU::CHIP_TYPE_MCU1 || chipMode == CHIP_TYPE_MCU::CHIP_TYPE_MCU2 ||
        chipMode == CHIP_TYPE_MCU::CHIP_TYPE_MCU3) {
        return true;
    }
    return false;
}

int BurnDlgMcu::GetChipMode() const
{
    return ui->cbChipModel->currentData().toInt();
}

bool BurnDlgMcu::IniReadMemory(QSettings *&settings, const QString &absConfigPath) const
{
    if (settings != nullptr) {
        delete settings;
        settings = nullptr;
    }
    /* Initialize and read the INI file object. */
    settings = new (std::nothrow)QSettings(absConfigPath, QSettings::IniFormat);
    if (settings == nullptr) {
        return false;
    }
    return true;
}

bool BurnDlgMcu::ReadChipConfigIni()
{
    if (configIniRead == nullptr) {
        return false;
    }
    QString chipName = ui->cbChipModel->currentText();
    if (chipName.contains("auto")) {
        chipName = "auto";
    }
    QString chipConfigFilePath = configIniRead->value("path/" + chipName).toString();
    QString absChipConfigFilePath = Global::GetAppConfigPath() + "\\config_mcu\\" + chipConfigFilePath;
    if (!BurnDlgMcu::IsFileExist(absChipConfigFilePath)) {
        QMessageBox::information(nullptr, stringClass.GetInformation(),
                                 stringClass.GetNotInfoFileTips().arg(absChipConfigFilePath));
        return false;
    }
    bool ret = IniReadMemory(chipIniRead, absChipConfigFilePath);
    if (!ret || chipIniRead->allKeys().size() == 0) {
        QMessageBox::information(nullptr, stringClass.GetInformation(),
                                 stringClass.GetNotReadPermissionTips().arg(absChipConfigFilePath));
        return false;
    }
    return true;
}

void BurnDlgMcu::ChipModeChangeInit()
{
    GetDefaultInfo();            /* get loader file path */
    TransmissionModeInit();     /* Initializing the transmission mode */
    BaudRateListInit();         /* Baud rate drop-down list box initialization */
    BaudRateUSBListInit();
    CANBaudRateListInit();
    SPIBaudRateListInit();
    I2CBaudRateListInit();
    IniFrequencies();
    IniDebugMode();
    ShowHistoryConfig();
}

void BurnDlgMcu::ShowInfoAreaUI()
{
    if (chipIniRead == nullptr) {
        return;
    }
    QStringList keyList = chipIniRead->allKeys();
    isInfoPart = false;
    for (QString key : keyList) {
        if (key.contains("infoPart")) {
            isInfoPart = true;
        }
    }
}

void BurnDlgMcu::GetDefaultInfo()
{
    loaderPath = "";
    loaderAddress = 0;
    targetFileJTAG = "";
    targetFileSWD = "";
    targetFileInfoJTAG = "";
    targetFileInfoSWD = "";
    chipIDAddress = 0;
    chipIDSize = 0;
    if (chipIniRead == nullptr) {
        return;
    }
    QString loaderFilePath = chipIniRead->value("loaderInfo/path").toString();
    if (loaderFilePath != "") {
        loaderPath = Global::GetAppConfigPath() + "\\config_mcu\\" + loaderFilePath;
    }
    QString loaderAddressStr = chipIniRead->value("loaderInfo/address").toString();
    loaderAddress = loaderAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString sramStartAddressStr = chipIniRead->value("loaderInfo/sram_start_address").toString();
    sramStartAddress = sramStartAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString sramEndAddressStr = chipIniRead->value("loaderInfo/sram_end_address").toString();
    sramEndAddress = sramEndAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString targetAddressStr = chipIniRead->value("targetInfo/address").toString();
    targetAddress = targetAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString parameterStartAddressStr = chipIniRead->value("parameterInfo/parameterStartAddress").toString();
    parameterStartAddress = parameterStartAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString mainStartAddressStr = chipIniRead->value("mainInfo/startAddress").toString();
    mainStartAddress = mainStartAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString mainSizeStr = chipIniRead->value("mainInfo/size").toString();
    mainSize = mainSizeStr.toULong();

    QString uploadStartAddressStr = chipIniRead->value("mainInfo/uploadStartAddress").toString();
    uploadStartAddress = uploadStartAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    QString uploadSizeStr = chipIniRead->value("mainInfo/uploadSize").toString();
    uploadSize = uploadSizeStr.toULong();

    QString infoStartAddressStr = chipIniRead->value("mainInfo/infoStartAddress").toString();
    infoStartAddress = infoStartAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);

    targetFileJTAG = chipIniRead->value("JTAGInfo/targetFileJTAG").toString();
    targetFileSWD = chipIniRead->value("JTAGInfo/targetFileSWD").toString();
    targetFileInfoJTAG = chipIniRead->value("JTAGInfo/targetFileInfoJTAG").toString();
    targetFileInfoSWD = chipIniRead->value("JTAGInfo/targetFileInfoSWD").toString();

    QString chipIDAddressStr = chipIniRead->value("parameterInfo/chipIdAddress").toString();
    chipIDAddress = chipIDAddressStr.toULong(Q_NULLPTR, SYSTEM_NUM_16);
    QString chipIDSizeStr = chipIniRead->value("parameterInfo/chipIdSize").toString();
    chipIDSize = chipIDSizeStr.toULong();

    QString eraseBaseNumStr = chipIniRead->value("parameterInfo/eraseBaseNum").toString();
    eraseBaseNum = (eraseBaseNumStr.toULong() != 0) ? eraseBaseNumStr.toULong() : 1;
}

void BurnDlgMcu::TransmissionModeInit()
{
    ui->cbTransferMethod->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "transmissionMode", ui->cbTransferMethod, systemNum);
}

void BurnDlgMcu::BaudRateListInit()
{
    ui->cbBaudrateUart->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "baudRate", ui->cbBaudrateUart, systemNum);
}

void BurnDlgMcu::BaudRateUSBListInit()
{
    ui->cbBaudrateUSB->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "baudRate", ui->cbBaudrateUSB, systemNum);
}

void BurnDlgMcu::CANBaudRateListInit()
{
    ui->cbBaudrateCan->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "canbaudRate", ui->cbBaudrateCan, systemNum);
}

void BurnDlgMcu::SPIBaudRateListInit()
{
    ui->cbRateSPI->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "SPIBaudRate", ui->cbRateSPI, systemNum);
}

void BurnDlgMcu::I2CBaudRateListInit()
{
    ui->cbRateI2C->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "I2CBaudRate", ui->cbRateI2C, systemNum);
}

void BurnDlgMcu::IniFrequencies()
{
    ui->cbFreq->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "frequencies", ui->cbFreq, systemNum);
}

void BurnDlgMcu::IniDebugMode()
{
    ui->cbDebugger->clear();
    systemNum = SYSTEM_NUM_10;
    ShowQComboBox(chipIniRead, "debugMode", ui->cbDebugger, systemNum);
}

void BurnDlgMcu::ShowHistoryConfig() const
{
    QString configFilePath = Global::GetAppConfigPath() + "\\config_mcu\\temp\\" +
                             ui->cbChipModel->currentText() + "Config.ini";
    if (!IsFileExist(configFilePath)) {
        return;
    }

    QSettings *configIniReadSettings = new (std::nothrow)QSettings(configFilePath, QSettings::IniFormat);
    if (configIniReadSettings == nullptr) {
        return;
    }

    ui->cbTransferMethod->setCurrentIndex(configIniReadSettings->value("config/transmissionMode").toInt());
    ui->cbCom->setCurrentText(configIniReadSettings->value("config/comboBox").toString());
    ui->cbBaudrateUart->setCurrentIndex(configIniReadSettings->value("config/baudRateList").toInt());
    ui->cbBaudrateUSB->setCurrentIndex(configIniReadSettings->value("config/baudRateUsb").toInt());
    ui->cbFreq->setCurrentIndex(configIniReadSettings->value("config/frequencies").toInt());
    ui->cbDebugger->setCurrentIndex(configIniReadSettings->value("config/debugMode").toInt());
    ui->cbBaudrateCan->setCurrentIndex(configIniReadSettings->value("config/canBaudRateList").toInt());
    ui->cbRateI2C->setCurrentIndex(configIniReadSettings->value("config/I2CBaudRate").toInt());
    ui->cbRateSPI->setCurrentIndex(configIniReadSettings->value("config/SPIBaudRate").toInt());
    ui->cbReadBack->setChecked(configIniReadSettings->value("config/isCheck").toBool());
    ui->cbRunDirectly->setChecked(configIniReadSettings->value("config/isRun").toBool());
}

void BurnDlgMcu::SlotTransferMethodCurrentIndexChanged(const QString &arg1) const
{
    Q_UNUSED(arg1);
    if (chipIniRead == nullptr) {
        return;
    }
    HideConfigComponent();
    QString transmissionModeName = ui->cbTransferMethod->currentText();
    if (GetTransmissionMode() == UART_MODE) {
        SetUIComboBoxDisplay(true);
        SetUIBaudRateUartDisplay(true);
    } else if (GetTransmissionMode() == UART_USB_MODE) {
        SetUIBaudRateUSBDisplay(true);
    } else if (GetTransmissionMode() == JTAG_MODE || GetTransmissionMode() == SWD_MODE) {
        SetUIFrequenciesDisplay(true);
        SetUIDebugModeDisplay(true);
    } else if (GetTransmissionMode() == CAN_MODE) {
        SetUICANBaudRateListDisplay(true);
    } else if (GetTransmissionMode() == I2C_MODE) {
        SetUII2CRateDisplay(true);
    } else if (GetTransmissionMode() == SPI_MODE) {
        SetUISPIRateDisplay(true);
    }
}

void BurnDlgMcu::HideConfigComponent() const
{
    SetUIComboBoxDisplay(false);
    SetUIBaudRateUartDisplay(false);
    SetUIBaudRateUSBDisplay(false);
    SetUIFrequenciesDisplay(false);
    SetUIDebugModeDisplay(false);
    SetUICANBaudRateListDisplay(false);
    SetUII2CRateDisplay(false);
    SetUISPIRateDisplay(false);
}

void BurnDlgMcu::SetUIComboBoxDisplay(bool isEnable) const
{
    ui->lbCom->setVisible(isEnable);
    ui->cbCom->setVisible(isEnable);
}

void BurnDlgMcu::SetUIBaudRateUartDisplay(bool isEnable) const
{
    ui->lbBaudrateUart->setVisible(isEnable);
    ui->cbBaudrateUart->setVisible(isEnable);
}

void BurnDlgMcu::SetUIBaudRateUSBDisplay(bool isEnable) const
{
    ui->lbBaudrateUSB->setVisible(isEnable);
    ui->cbBaudrateUSB->setVisible(isEnable);
}


void BurnDlgMcu::SetUIFrequenciesDisplay(bool isEnable) const
{
    ui->lbFreq->setVisible(isEnable);
    ui->cbFreq->setVisible(isEnable);
}

void BurnDlgMcu::SetUIDebugModeDisplay(bool isEnable) const
{
    ui->lbDebugger->setVisible(isEnable);
    ui->cbDebugger->setVisible(isEnable);
}

void BurnDlgMcu::SetUICANBaudRateListDisplay(bool isEnable) const
{
    ui->lbBaudrateCan->setVisible(isEnable);
    ui->cbBaudrateCan->setVisible(isEnable);
}

void BurnDlgMcu::SetUII2CRateDisplay(bool isEnable) const
{
    ui->lbRateI2C->setVisible(isEnable);
    ui->cbRateI2C->setVisible(isEnable);
}

void BurnDlgMcu::SetUISPIRateDisplay(bool isEnable) const
{
    ui->lbRateSPI->setVisible(isEnable);
    ui->cbRateSPI->setVisible(isEnable);
}

int BurnDlgMcu::GetTransmissionMode() const
{
    return ui->cbTransferMethod->currentData().toInt();
}

void BurnDlgMcu::SlotCbnSetfocusComboCom() const
{
    if (portType == Base::TCP_PORT) {
        return;
    }
    QString strPort = ui->cbCom->currentText();
    ui->cbCom->clear();
    QStringList strListPort;
    DataConvertor::RefreshComList(strListPort);
    ui->cbCom->addItems(strListPort);
    for (int i = 0; i < strListPort.size(); i++) {
        if (strListPort.at(i) == strPort) {
            ui->cbCom->setCurrentText(strPort);
        }
    }
}

void BurnDlgMcu::SlotBnClickedButtonSelectfile()
{
    QString filePath = QFileDialog::getOpenFileName(this, tr("Select File"), "", stringClass.GetIdsString32941());
    if (!filePath.isEmpty()) {
        AnalyseBinFile(filePath);
    }
}

void BurnDlgMcu::AnalyseBinFile(QString filePath)
{
    if (burnCtrl == nullptr /* || burnCtrl->IsBusy() */) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }
    ui->lineEditSeleteFile->setText(filePath);
    QMap<int, bool> mapLastBinCheck = binModel->GetMapCheck();
    QMap<int, BIN_INFO> mapLastBinInfo = binModel->GetMapBinFileInfo();
    binModel->ClearData();
    BIN_INFO_ARRAY infoArray;
    QString version;
    QMap<int, BIN_INFO> mapBinInfo = binModel->GetMapBinFileInfo();
    QMap<int, bool> mapCheck;
    QString fileName = ui->lineEditSeleteFile->text();
    GetFileInfo(fileName);
    DataConvertor::AnalysMultifBin(fileName, infoArray, version, isEncrypt, encryptBuffer);
    if (infoArray.GetSize() == 1 && infoArray.GetAt(0).fileName.isEmpty()) {
        int currentSize = mapBinInfo.size();
        mapBinInfo[currentSize] = infoArray.GetAt(0);
        mapBinInfo[currentSize].burnAddr = "0x" + QString::number(targetAddress, SYSTEM_NUM_16);
        mapBinInfo[currentSize].burnSize = mapBinInfo[currentSize].fileSize;
        mapBinInfo[currentSize].path = ui->lineEditSeleteFile->text();
        mapCheck[currentSize] = true;
    } else {
        for (int i = 0; i < infoArray.GetSize(); i++) {
            infoArray.GetAt(i).path = ui->lineEditSeleteFile->text();
            mapBinInfo[mapBinInfo.size()] = infoArray.GetAt(i);
        }
        for (int i = 0; i < mapBinInfo.size(); i++) {
            mapCheck[i] = true;
        }
    }

    binModel->FetchData(mapCheck);
    binModel->FetchData(mapBinInfo);
}

void BurnDlgMcu::InitTableView() const
{
    binModel->SetEditableCheckbox(isCheckAble);
    ui->tableView->setModel(binModel);
    ui->tableView->setDragEnabled(true);
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableView->setDefaultDropAction(Qt::MoveAction);
    ui->tableView->setDragDropMode(QAbstractItemView::InternalMove);
    ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_CHECK, COLUMN_WIDTH_SIZE_20);
    ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_ADD, COLUMN_WIDTH_SIZE_20);
    ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_DELETE, COLUMN_WIDTH_SIZE_20);
    ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_NAME, COLUMN_WIDTH_SIZE_100);
    ui->tableView->setColumnWidth(TABLEVIEW_COLUMN_PAHT, COLUMN_WIDTH_SIZE_200);
    ui->tableView->setMinimumHeight(COLUMN_MINIMUM_HEIGHT_SIZE_192);
    ui->tableView->horizontalHeader()->setSectionResizeMode(TABLEVIEW_COLUMN_CHECK, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(TABLEVIEW_COLUMN_ADD, QHeaderView::Fixed);
    ui->tableView->horizontalHeader()->setSectionResizeMode(TABLEVIEW_COLUMN_DELETE, QHeaderView::Fixed);
}

void BurnDlgMcu::InitBurnCtrl()
{
    BurnCtrlFaction faction;
    burnCtrl = faction.GetBurnCtrl(chipType);
    if (burnCtrl != nullptr) {
        burnCtrl->SetBurnDlg(this);
    }
}

void BurnDlgMcu::SlotConnectBtnClicked()
{
    if (burnCtrl == nullptr) {
        QMessageBox::critical(this, stringClass.GetMessageError(),
                              stringClass.GetIdsString32984(), stringClass.GetYes());
        return;
    }
    if (ui->pbConnect->text() == stringClass.GetIdsString32918()) {
        burnCtrl->SetIsCancel(false);
        int chipModel = ui->cbChipModel->currentData().toInt();
        if (chipModel == 0) {
            QMessageBox::information(nullptr, stringClass.GetInformation(), tr("Please select the chip model first"));
            return;
        }
        if (chipModel == CHIP_TYPE_AUTO && (GetTransmissionMode() == JTAG_MODE || GetTransmissionMode() == SWD_MODE)) {
            QMessageBox::information(nullptr, stringClass.GetInformation(),
                                     tr("JTAG/SWD does not support automatic recognition," \
                                     " please choose other connection methods"));
            return;
        }
        SaveCurrentConfig(ui->cbChipModel->currentText());
        ui->pbConnect->setEnabled(true);
        SetMcuConfig2BurnCtrl();
        McuChipId mcuChipId;
        mcuChipId.chipIDAddress = chipIDAddress;
        mcuChipId.chipIDSize = chipIDSize;
        burnCtrl->SetChipId(mcuChipId);
        emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_STARTCONNECT), 0, 0);
        ui->pbConnect->setText(stringClass.GetDisconnect());
        paramDlg->SetIsConnect(true);
    } else {
        SlotShowLog(QString(tr("Disconnected.\n")), false, Qt::black);
        burnCtrl->SetIsCancel(true);
        burnCtrl->BurnCtrlCancel();
        emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_RESETUIANDFSM), 0, 0);
        ui->pbConnect->setText(stringClass.GetIdsString32918());
        paramDlg->SetIsConnect(false);
    }
}

void BurnDlgMcu::SetMcuConfig2BurnCtrl()
{
    int chipModel = ui->cbChipModel->currentData().toInt();
    burnCtrl->SetChipModel(chipModel);
    McuConfig mcuConfig;
    mcuConfig.portName = ui->cbCom->currentText();
    mcuConfig.baudRate = GetTransmissionMode() == UART_MODE ?
                         ui->cbBaudrateUart->currentText().toInt() :
                         ui->cbBaudrateUSB->currentText().toInt();
    mcuConfig.chipModeData = ui->cbChipModel->currentData().toInt();
    mcuConfig.i2cBaudRate = ui->cbRateI2C->currentData().toInt();
    mcuConfig.spiBaudRate = ui->cbRateSPI->currentData().toInt();
    mcuConfig.canBaudRate = ui->cbBaudrateCan->currentData().toInt();
    mcuConfig.deviceAddress = GetTransmissionMode() == I2C_MODE ? I2C_DEVICE_ADDRESS : 0;
    mcuConfig.debugMode = ui->cbDebugger->currentData().toInt();
    mcuConfig.freq = ui->cbFreq->currentData().toInt();
    burnCtrl->SetMcuConfig(mcuConfig);
    McuJtagSwd jtagSwd;
    jtagSwd.targetFileSWD = targetFileSWD;
    jtagSwd.targetFileJTAG = targetFileJTAG;
    jtagSwd.targetFileInfoSWD = targetFileInfoSWD;
    jtagSwd.targetFileInfoJTAG = targetFileInfoJTAG;
    burnCtrl->SetJtagSwd(jtagSwd);
    burnCtrl->SetTransmissionMode(GetTransmissionMode());
}

bool BurnDlgMcu::SaveCurrentConfig(QString chipName) const
{
    QString configFilePath = Global::GetAppConfigPath() + "\\config_mcu\\temp\\" + chipName + "Config.ini";
    if (!IsFileExist(configFilePath)) {
        return false;
    }

    QSettings *configIniReadSettings = new (std::nothrow)QSettings(configFilePath, QSettings::IniFormat);
    if (configIniReadSettings == nullptr) {
        return false;
    }

    configIniReadSettings->setValue("config/transmissionMode", ui->cbTransferMethod->currentIndex());
    configIniReadSettings->setValue("config/comboBox", ui->cbCom->currentText());
    configIniReadSettings->setValue("config/baudRateList", ui->cbBaudrateUart->currentIndex());
    configIniReadSettings->setValue("config/baudRateUsb", ui->cbBaudrateUSB->currentIndex());
    configIniReadSettings->setValue("config/frequencies", ui->cbFreq->currentIndex());
    configIniReadSettings->setValue("config/debugMode", ui->cbDebugger->currentIndex());
    configIniReadSettings->setValue("config/canBaudRateList", ui->cbBaudrateCan->currentIndex());
    configIniReadSettings->setValue("config/I2CBaudRate", ui->cbRateI2C->currentIndex());
    configIniReadSettings->setValue("config/SPIBaudRate", ui->cbRateSPI->currentIndex());
    configIniReadSettings->setValue("config/isCheck", ui->cbReadBack->isChecked());
    configIniReadSettings->setValue("config/isRun", ui->cbRunDirectly->isChecked());
    return true;
}

void BurnDlgMcu::SlotShowLog(QString logStr, bool isShowTime, QColor color) const
{
    if (logStr == "") {
        return;
    }
    QDateTime time = QDateTime::currentDateTime();
    QString timeTip = time.toString("yyyy-MM-dd hh:mm:ss");
    QString log = logStr;
    static bool isEnterFlag = false;
    if (logStr == "#") {
        if (!isEnterFlag) {
            isEnterFlag = true;
            log = '\n' + logStr;
        } else {
            log = logStr;
        }
    } else {
        if (isEnterFlag) {
            isEnterFlag = false;
            if (isShowTime) {
                log = '\n' + timeTip + ": "+ logStr;
            } else {
                log = '\n' + logStr;
            }
        }
    }

    ui->textEditReceive->moveCursor(QTextCursor::End);
    QTextCharFormat fmt;
    fmt.setForeground(QBrush(color));
    if (log.toLower().contains("error")) {
        fmt.setForeground(QBrush(Qt::red));
    }
    ui->textEditReceive->mergeCurrentCharFormat(fmt);
    ui->textEditReceive->insertPlainText(log);
}

void BurnDlgMcu::SlotSetConnectStatus(bool isEnable)
{
    if (isEnable) {
        ui->pbConnect->setText(stringClass.GetDisconnect());
        paramDlg->SetIsConnect(true);
    } else {
        ui->pbConnect->setText(stringClass.GetIdsString32918());
        paramDlg->SetIsConnect(false);
    }
}

void BurnDlgMcu::SlotSetTips(const QString &title, const QString &text) const
{
    QMessageBox::information(nullptr, title, text);
}

void BurnDlgMcu::SlotChangeChipModeByChipId(QString &chipName, uint chipId)
{
    if (configIniRead == nullptr) {
        return;
    }
    configIniRead->beginGroup("chipIdToChipName");
    QStringList chipIds = configIniRead->childKeys();
    configIniRead->endGroup();

    for (QString id : chipIds) {
        QStringList mcuNameList = configIniRead->value("/chipIdToChipName/" + id).toString().split("|");
        if (id == QString::number(chipId, SYSTEM_NUM_16)) {
            chipName = mcuNameList.contains(ui->cbChipModel->currentText()) ?
                                            ui->cbChipModel->currentText() : mcuNameList[0];
            break;
        }
    }
    SaveCurrentConfig(chipName);
    if (chipName == ui->cbChipModel->currentText()) {
        return;
    }

    ChangeChipMode(chipName);
}

bool BurnDlgMcu::ChangeChipMode(QString changeChipName)
{
    for (int i = 0; i < ui->cbChipModel->count(); i++) {
        if (ui->cbChipModel->itemText(i) != changeChipName) {
            continue;
        }
        SetMcuConfig2BurnCtrl();
        emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_MCU_REOPEN), 0, 0);
        ui->cbChipModel->setCurrentIndex(i);
        return true;
    }
    return false;
}

void BurnDlgMcu::SlotBnClickedButtonStartburn()
{
    if (ui->btnStartBurn->text() == stringClass.GetStopBurn()) {
        SetEnableBtn(true);
        burnCtrl->SetIsCancel(TRUE);
        burnCtrl->BurnCtrlCancel();
        return;
    }
    UpdateList();
    ui->progressBarReceive->setValue(0);
    burnCtrl->SetIsCancel(FALSE);
    int i = 0;
    QMap<int, BIN_INFO> binInfo = binModel->GetMapBinFileInfo();
    QMap<int, BIN_INFO> checkBinInfo;
    QMap<int, bool> binCheck = binModel->GetMapCheck();
    for (auto it = binInfo.begin(); it != binInfo.end(); it++) {
        if (binCheck[it.key()]) {
            BIN_INFO_ARRAY infoArray;
            QString version;
            checkBinInfo[i++] = it.value();
        }
    }
    if (checkBinInfo.size() == 0 || (!QFile(ui->lineEditSeleteFile->text()).exists())) {
        QMessageBox::warning(nullptr, MESSAGE_BURN_TOOL, stringClass.GetNoValidFlashFile());
        return;
    }

    MainStartAddrInfo info;
    info.mainStartAddress = mainStartAddress;
    info.mainSize = mainSize;
    burnCtrl->SetInfoStartAddress(infoStartAddress);
    burnCtrl->SetMainStartAddress(info);
    burnCtrl->SetBurnPath(ui->lineEditSeleteFile->text());
    SramAddrInfo sainfo;
    sainfo.sramStartAddress = sramStartAddress;
    sainfo.sramEndAddress = sramEndAddress;
    burnCtrl->SetSramAddrInfo(sainfo);
    burnCtrl->SetIsReadBack(ui->cbReadBack->isChecked());
    burnCtrl->SetIsRun(ui->cbRunDirectly->isChecked());
    burnCtrl->SetLoaderInfo(loaderPath, loaderAddress);
    QString str;
    burnCtrl->SetParameterSaveInfo(str, eraseBaseNum);

    burnCtrl->InitBurnCmdByArray(checkBinInfo);
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_STARTBURN), 0, 0);
    SetEnableBtn(false);
}

void BurnDlgMcu::UpdateList()
{
    int nRow = binModel->rowCount();
    if (nRow > 0x1000) {
        return;
    }
    std::vector<QString> pathArray;
    for (int i = 0; i < nRow; i++) {
        if (binModel->GetCheck(i)) {
            QString path = binModel->GetValue(i, TABLEVIEW_COLUMN_PAHT);

            pathArray.push_back(path);
        }
    }
    std::vector<QString> result;
    for (auto item : pathArray) {
        bool needAddDlg3X = true;
        for (auto item2 : result) {
            if (item2 == item) {
                needAddDlg3X = false;
                break;
            }
        }
        if (needAddDlg3X) {
            result.push_back(item);
        }
    }
    QString version;
    for (auto item : result) {
        BIN_INFO_ARRAY infoArray;
        DataConvertor::AnalysMultifBin(item, infoArray, version, isEncrypt, encryptBuffer);
        UpdateList(infoArray);
    }
}

void BurnDlgMcu::UpdateList(BIN_INFO_ARRAY &info) const
{
    for (int i = 0; i < info.GetSize(); i++) {
        BIN_INFO item = info.GetAt(i);
        int colNum = binModel->rowCount(); // 取行数
        if (colNum > 0x1000) {
            break;
        }
        QMap<int, BIN_INFO> mapBinInfo;
        mapBinInfo.clear();
        mapBinInfo = binModel->GetMapBinFileInfo();
        for (int j = 0; j < colNum; j++) {
            if ((!item.fileName.isEmpty()) && binModel->GetCheck(j) &&
                item.path == mapBinInfo[j].path && item.fileName == mapBinInfo[j].fileName &&
                item.type == mapBinInfo[j].type && (mapBinInfo[j].fileIndex != item.fileIndex ||
                mapBinInfo[j].fileSize != item.fileSize || mapBinInfo[j].burnAddr != item.burnAddr ||
                mapBinInfo[j].burnSize != item.burnSize)) {
                mapBinInfo[j].fileIndex = item.fileIndex;
                mapBinInfo[j].fileSize = item.fileSize;
                mapBinInfo[j].burnAddr = item.burnAddr;
                mapBinInfo[j].burnSize = item.burnSize;
            } else if (item.fileName.isEmpty() && binModel->GetCheck(j) && item.path == mapBinInfo[j].path &&
                       item.fileSize != mapBinInfo[j].fileSize) {
                mapBinInfo[j].fileSize = item.fileSize;
            }
        }
        binModel->FetchData(mapBinInfo);
    }
}

bool BurnDlgMcu::GetFileInfo(QString &fileName)
{
    MemoryAddresses *addresses = new (std::nothrow)MemoryAddresses();
    if (addresses == nullptr) {
        return false;
    }
    addresses->addresses = nullptr;
    addresses->count = 0;
    if (!StartHexToBin(fileName, addresses)) {
        delete addresses;
        return false;
    }
    delete addresses;
    return true;
}

int BurnDlgMcu::ReadHexInfo(QString &fileName, MemoryAddresses *addresses) const
{
    FILE *inf = fopen(DataConvertor::CodeGB2312(fileName, "gbk").data(), "rb");
    if (inf == nullptr) {
        return FILE_OPEN_FAIL;
    }
    int success = ReadHex(inf, MemoryAddressesStore, addresses, 0);
    fclose(inf);
    if (success == 0) {
        return FILE_READ_FAIL;
    }
    return SUCCESS;
}

bool BurnDlgMcu::StartHexToBin(QString &fileName, MemoryAddresses * const &addresses)
{
    if (fileName.toLower().lastIndexOf(".hex") != -1) {
        int readRes = ReadHexInfo(fileName, addresses);
        if (readRes == FILE_OPEN_FAIL) {
            SlotSetTips(stringClass.GetAssert(), stringClass.GetNotReadAgainTips().arg(fileName));
            return false;
        }
        if (readRes == FILE_READ_FAIL) {
            SlotSetTips(stringClass.GetAssert(), stringClass.GetFileCorruptionTips().arg(fileName));
            return false;
        }
        QString hexToBinFilePath = Global::GetAppConfigPath() + "\\config_mcu\\temp\\hexToBin.bin";
        int toBinRes = HexToBin(fileName, hexToBinFilePath, *addresses);
        if (toBinRes == FILE_OPEN_FAIL) {
            SlotSetTips(stringClass.GetAssert(), stringClass.GetNotReadAgainTips().arg(fileName));
            return false;
        }
        if (toBinRes == FILE_WRITE_OPEN_FAIL) {
            SlotSetTips(stringClass.GetAssert(), stringClass.GetNotWriteAgainTips().arg(hexToBinFilePath));
            return false;
        }
        if (readRes == FAIL) {
            SlotSetTips(stringClass.GetAssert(), stringClass.GetFileCorruptionTips().arg(fileName));
            return false;
        }
        fileName = hexToBinFilePath;
    }
    return true;
}

int BurnDlgMcu::HexToBin(QString &hexName, QString &binName, MemoryAddresses &addresses) const
{
    int offset = 0;
    if (addresses.addresses != nullptr) {
        offset = *addresses.addresses;
    }

    int size = addresses.count;
    int bSize = size;
    FILE *inf = fopen(DataConvertor::CodeGB2312(hexName, "gbk").data(), "rb");
    if (inf == nullptr) {
        return FILE_OPEN_FAIL;
    }
    BYTE *b = new (std::nothrow)BYTE[bSize];
    if (b == nullptr) {
        return FAIL;
    }
    memset_s(b, bSize, 0xff, bSize);
    struct MemoryDesc md;
    md.p = b;
    md.offset = offset;
    md.size = size;
    md.sizeWritten = 0;
    int success = ReadHex(inf, MemoryDescStore, &md, 1);
    fclose(inf);
    if (success != 0) {
        FILE *outf = fopen(DataConvertor::CodeGB2312(binName, "gbk").data(), "wb");
        if (outf == nullptr) {
            delete[]b;
            return FILE_WRITE_OPEN_FAIL;
        }
        if (fwrite(b, 1, size, outf) != size) {
            delete[]b;
            return FILE_WRITE_FAIL;
        }
        fclose(outf);
    } else {
        delete[]b;
        return FAIL;
    }
    delete[]b;
    return SUCCESS;
}

void BurnDlgMcu::SlotSetProgress(double pos) const
{
    if (ui == nullptr) {
        return;
    }
    ui->progressBarReceive->setValue(pos);
}

void BurnDlgMcu::SlotInsertPlainText(const QString &editStr)
{
    if (editStr == "") {
        return;
    }
    QDateTime time = QDateTime::currentDateTime();
    QString timeTip = time.toString("yyyy-MM-dd hh:mm:ss");
    QString log = editStr;

    if (editStr == "#") {
        if (!isEnter) {
            isEnter = true;
            log = '\n' + editStr;
        } else {
            log = editStr;
        }
    } else {
        if (isEnter) {
            isEnter = false;
            log = '\n' + editStr;
        }
    }

    ui->textEditReceive->moveCursor(QTextCursor::End);
    QTextCharFormat fmt;
    if (log.toLower().contains("error")) {
        fmt.setForeground(QBrush(Qt::red));
    } else {
        fmt.setForeground(QBrush(Qt::black));
    }
    ui->textEditReceive->mergeCurrentCharFormat(fmt);
    ui->textEditReceive->insertPlainText(log);
    ui->textEditReceive->ensureCursorVisible();
}

void BurnDlgMcu::SlotBnClickedSelectTarget()
{
    if (ui == nullptr) {
        return;
    }
    QString filePath = QFileDialog::getSaveFileName(this, tr("Select File"), "", stringClass.GetIdsString32949());
    if (!filePath.isEmpty()) {
        ui->leSelectTarget->setText(filePath);
    }
}

void BurnDlgMcu::SlotBnClickedExport()
{
    QString readFilePath = ui->leSelectTarget->text();
    DWORD readAddress = ui->leAddr->text().toULong(Q_NULLPTR, SYSTEM_NUM_16);
    DWORD readSize = ui->leSize->text().toULong(Q_NULLPTR, SYSTEM_NUM_10);
    if (readFilePath.isEmpty()) {
        QMessageBox::information(nullptr, stringClass.GetInformation(), tr("The file saving path cannot be empty."));
        return;
    }

    if (ui->leAddr->text().isEmpty()) {
        QMessageBox::information(nullptr, stringClass.GetInformation(), tr("The read address cannot be empty."));
                return;
            }

    if (ui->leSize->text().isEmpty()) {
        QMessageBox::information(nullptr, stringClass.GetInformation(), tr("The read length cannot be empty."));
        return;
    }
    if (!CheckFlashAddressLegitimacy(readAddress, readSize, mainStartAddress, mainSize * KB_UNIT)) {
        SlotInsertPlainText(QString(tr("The read address must not be less than 0x%1,"
                                    " and the maximum read address must not exceed 0x%2."))
                            .arg(QString::number(mainStartAddress, SYSTEM_NUM_16))
                            .arg(QString::number(mainStartAddress + mainSize * KB_UNIT, SYSTEM_NUM_16)));
        return;
    }
    ExportInfo *exportInfo = new ExportInfo();
    if (exportInfo == nullptr) {
        return;
    }
    exportInfo->addr = readAddress;
    exportInfo->len = readSize;
    exportInfo->path = readFilePath;
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_EXPORT),
                       reinterpret_cast<WPARAM>(exportInfo),
                       sizeof(exportInfo));
    SetEnableBtn(false);
}

bool BurnDlgMcu::CheckFlashAddressLegitimacy(DWORD address, DWORD size,
    DWORD baseAddress, DWORD maxSize) const
{
    if (address < baseAddress) {
        return false;
    }
    if (address + size > baseAddress + maxSize) {
        return false;
    }
    return true;
}

void BurnDlgMcu::SlotBnClickedErase()
{
    DWORD eraseAddress = ui->leAddr->text().toULong(Q_NULLPTR, SYSTEM_NUM_16);
    DWORD eraseSize = ui->leSize->text().toULong(Q_NULLPTR, SYSTEM_NUM_10);
    if (ui->leAddr->text().isEmpty()) {
        QMessageBox::information(nullptr, stringClass.GetInformation(), tr("Erase address cannot be empty."));
        return;
    }

    if (ui->leSize->text().isEmpty()) {
        QMessageBox::information(nullptr, stringClass.GetInformation(), tr("Erase length cannot be empty."));
        return;
    }

    if (eraseAddress % ERASE_START_ADDRESS_BASE_BIT != 0) {
        QMessageBox::information(nullptr, stringClass.GetInformation(),
                                 QString(tr("The start address must be a multiple of %1.")).
                                 arg(ERASE_START_ADDRESS_BASE_BIT));
        return;
    }

    if (eraseSize % ERASE_START_ADDRESS_BASE_BIT != 0) {
        QMessageBox::information(nullptr, stringClass.GetInformation(),
                                 QString(tr("The erase size must be a multiple of %1.")).
                                 arg(ERASE_START_ADDRESS_BASE_BIT));
        return;
    }
    if (!CheckFlashAddressLegitimacy(eraseAddress, eraseSize, mainStartAddress, mainSize * KB_UNIT)) {
        QString str = QString(tr("The erase address must not be less than 0x%1, "
                              "and the maximum erase address must not exceed 0x%2."))
                .arg(QString::number(mainStartAddress, SYSTEM_NUM_16))
                .arg(QString::number(mainStartAddress + mainSize * KB_UNIT, SYSTEM_NUM_16));
        return;
    }

    ExportInfo *eraseInfo = new ExportInfo();
    if (eraseInfo == nullptr) {
        return;
    }
    SaveCurrentConfig(ui->cbChipModel->currentText());
    eraseInfo->addr = eraseAddress;
    eraseInfo->len = eraseSize;
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_ERASE),
                       reinterpret_cast<WPARAM>(eraseInfo),
                       sizeof(eraseInfo));
}

void BurnDlgMcu::SlotEraseAllMemory()
{
    ExportInfo *eraseInfo = new ExportInfo();
    if (eraseInfo == nullptr) {
        return;
    }
    SaveCurrentConfig(ui->cbChipModel->currentText());
    eraseInfo->addr = mainStartAddress;
    eraseInfo->len = mainSize * KB_UNIT;
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_ERASE),
                       reinterpret_cast<WPARAM>(eraseInfo),
                       sizeof(eraseInfo));
}

void BurnDlgMcu::SlotParamSetting()
{
    if (chipIniRead == nullptr) {
        return;
    }
    paramDlg->SetBurnCtrl(burnCtrl);
    paramDlg->SetIniSettings(chipIniRead);
    ShowInfoAreaUI();
    paramDlg->ShowInfoAreaUI(isInfoPart);
    paramDlg->ShowTable("parameter");
    paramDlg->SetParameterEnableValue("parameterEnableValue");
    paramDlg->GetinfoUnlockData(chipIniRead);
    paramDlg->SetTransmissionMode(ui->cbTransferMethod->currentText().toLower());
    paramDlg->SetChipMode(GetChipMode());
    paramDlg->GetParameterBaseInfo();
    paramDlg->GetProtectionPara();        /* get protection parameter */
    paramDlg->show();
    paramDlg->SetCurrentPath();
}

void BurnDlgMcu::SlotGetParameter()
{
    MainStartAddrInfo info;
    info.mainStartAddress = mainStartAddress;
    info.mainSize = mainSize;
    burnCtrl->SetInfoStartAddress(infoStartAddress);
    burnCtrl->SetMainStartAddress(info);
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_GET_PARAMETER),
                                static_cast<WPARAM>(0),
                                0);
}

void BurnDlgMcu::SlotSetParameter()
{
    MainStartAddrInfo info;
    info.mainStartAddress = mainStartAddress;
    info.mainSize = mainSize;
    burnCtrl->SetInfoStartAddress(infoStartAddress);
    burnCtrl->SetMainStartAddress(info);
    emit SignalSendMsgInBurnDlg(static_cast<long>(WiteThreadMsg::WITE_THREAD_MSG_SET_PARAMETER),
                                static_cast<WPARAM>(0),
                                0);
}

void BurnDlgMcu::SlotBurnFileFinish()
{
    if (ui == nullptr) {
        return;
    }
    SetEnableBtn(true);
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
    SlotInsertPlainText(stringClass.GetIdsString32880() + "\n");
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
}

void BurnDlgMcu::SlotBurnFileFailed()
{
    if (ui == nullptr) {
        return;
    }
    SetEnableBtn(true);
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
    SlotInsertPlainText(stringClass.GetIdsString32881());
    SlotInsertPlainText(IDS_STRING_32879 + "\n");
    ui->progressBarReceive->setValue(0);
}

void BurnDlgMcu::SetEnableBtn(bool enable) const
{
    ui->btnStartBurn->setEnabled(enable);
    ui->pbExport->setEnabled(enable);
    ui->pbErase->setEnabled(enable);
    ui->pbEraseAll->setEnabled(enable);
    ui->pbParamSetting->setEnabled(enable);
    if (IsFirstSeriesChip(GetChipMode())) {
        ui->cbRunDirectly->setEnabled(false);
    } else {
        ui->cbRunDirectly->setEnabled(enable);
    }
    ui->cbReadBack->setEnabled(enable);
    ui->cbChipModel->setEnabled(enable);
    ui->cbTransferMethod->setEnabled(enable);
    ui->cbCom->setEnabled(enable);
    ui->cbBaudrateCan->setEnabled(enable);
    ui->cbBaudrateUSB->setEnabled(enable);
    ui->cbBaudrateUart->setEnabled(enable);
    ui->cbChipModel->setEnabled(enable);
    ui->cbDebugger->setEnabled(enable);
    ui->cbFreq->setEnabled(enable);
    ui->cbRateI2C->setEnabled(enable);
    ui->cbRateSPI->setEnabled(enable);
    ui->pbConnect->setEnabled(enable);
}

void BurnDlgMcu::SlotExportFinish() const
{
    if (ui == nullptr) {
        return;
    }
    SetEnableBtn(true);
}

void BurnDlgMcu::SlotExportFail() const
{
    if (ui == nullptr) {
        return;
    }
    SetEnableBtn(true);
}

void BurnDlgMcu::SlotBnClickedMultipleBurn()
{
    if (burnCtrl == nullptr || ui == nullptr) {
        return;
    }
    if (!isMultipleBurnOpen) {
        QMap<int, BIN_INFO> infoArray;
        GetCmdInfoArray(infoArray);
        if (infoArray.size() == 0) {
            QMessageBox::critical(this, stringClass.GetMessageError(),
                                  stringClass.GetIdsString33069(), stringClass.GetYes());
            return;
        }
        int result = QMessageBox::information(this, stringClass.GetInformation(),
                                              stringClass.GetIdsString33070(), stringClass.GetYes(),
                                              stringClass.GetNo());
        if (result == 1) {
            return;
        }
        burnCtrl->SetIsCancel(TRUE);
        burnCtrl->BurnCtrlCancel();
        isMultipleBurnOpen = true;
        if (burnCtrl->IsComOpen()) {
            emit SignalSendMsgInBurnDlg(static_cast<long int>(WiteThreadMsg::WITE_THREAD_MSG_RESETUIANDFSM), 0, 0);
        }
        ui->btnStartBurn->setEnabled(false);
        FillParamAndShow(infoArray);
    }
}

void BurnDlgMcu::SetMcuConfigValue(McuConfig &mcuConfig) const
{
    mcuConfig.portName = ui->cbCom->currentText();
    mcuConfig.baudRate = ui->cbBaudrateUart->currentText().toInt();
    mcuConfig.chipModeData = ui->cbChipModel->currentData().toInt();
    mcuConfig.i2cBaudRate = ui->cbRateI2C->currentData().toInt();
    mcuConfig.spiBaudRate = ui->cbRateSPI->currentData().toInt();
    mcuConfig.canBaudRate = ui->cbBaudrateCan->currentData().toInt();
    mcuConfig.deviceAddress = 0;
    mcuConfig.debugMode = ui->cbDebugger->currentData().toInt();
    mcuConfig.freq = ui->cbFreq->currentData().toInt();
}

void BurnDlgMcu::SetMcuJtagSwdValue(McuJtagSwd &jtagSwd)
{
    jtagSwd.targetFileSWD = targetFileSWD;
    jtagSwd.targetFileJTAG = targetFileJTAG;
    jtagSwd.targetFileInfoSWD = targetFileInfoSWD;
    jtagSwd.targetFileInfoJTAG = targetFileInfoJTAG;
}

void BurnDlgMcu::ActionOfMultipleBurnDlgAfterSetInfoArray()
{
    QString strFilePath = ui->lineEditSeleteFile->text();
    multipleBurnDlg->SetInfoArray(strFilePath);
    connect(multipleBurnDlg, &MultipleBurnDlg::SignalClose, this, &BurnDlgMcu::SlotMultipleBurnDlgClose);
    multipleBurnDlg->SetCtrlNum(burnCtrl->GetMultiBurnTotalNum());
    multipleBurnDlg->SetOneLineNum(burnCtrl->GetMultiBurnNumPerLine());
    multipleBurnDlg->SetIndenpendentBurn(burnCtrl->GetMultiBurnIndenpendentBurn());
    multipleBurnDlg->SetIsResetAfterSuccess(burnCtrl->GetIsResetAfterSuccess());
    multipleBurnDlg->SetYModemEachPackageSize(burnCtrl->GetYModemEachPackageSize());
}

void BurnDlgMcu::ActionOfMultipleBurnDlgAfterSetSramAddrInfo()
{
    multipleBurnDlg->SetIsReadBack(ui->cbReadBack->isChecked());
    multipleBurnDlg->SetIsRun(ui->cbRunDirectly->isChecked());
    multipleBurnDlg->SetLoaderInfo(loaderPath, loaderAddress);
    QString str = "";
    multipleBurnDlg->SetParameterSaveInfo(str, eraseBaseNum);
    multipleBurnDlg->InitUi();
    multipleBurnDlg->show();
}

void BurnDlgMcu::FillParamAndShow(const QMap<int, BIN_INFO> &info)
{
    if (burnCtrl == nullptr || ui == nullptr) {
        return;
    }
    if (multipleBurnDlg != nullptr) {
        delete multipleBurnDlg;
        multipleBurnDlg = nullptr;
    }
    multipleBurnDlg = new MultipleBurnDlg();
    if (multipleBurnDlg == nullptr) {
        isMultipleBurnOpen = false;
        return;
    }
    multipleBurnDlg->SetChipType(chipType);
    int chipModel = ui->cbChipModel->currentData().toInt();
    multipleBurnDlg->SetChipModel(chipModel);
    McuConfig mcuConfig;
    SetMcuConfigValue(mcuConfig);
    multipleBurnDlg->SetMcuConfig(mcuConfig);
    McuJtagSwd jtagSwd;
    SetMcuJtagSwdValue(jtagSwd);
    multipleBurnDlg->SetJtagSwd(jtagSwd);
    multipleBurnDlg->SetTransmissionMode(UART_MODE);
    McuChipId mcuChipId;
    mcuChipId.chipIDAddress = chipIDAddress;
    mcuChipId.chipIDSize = chipIDSize;
    multipleBurnDlg->SetChipId(mcuChipId);
    multipleBurnDlg->SetSecConn(burnCtrl->IsSecConn());
    multipleBurnDlg->SetPeriod(burnCtrl->GetPeriod());

    multipleBurnDlg->SetInfoArray(info);
    ActionOfMultipleBurnDlgAfterSetInfoArray();

    MainStartAddrInfo mainStartAddrInfo;
    mainStartAddrInfo.mainStartAddress = mainStartAddress;
    mainStartAddrInfo.mainSize = mainSize;
    multipleBurnDlg->SetInfoStartAddress(infoStartAddress);
    multipleBurnDlg->SetMainStartAddress(mainStartAddrInfo);
    SramAddrInfo sainfo;
    sainfo.sramStartAddress = sramStartAddress;
    sainfo.sramEndAddress = sramEndAddress;
    multipleBurnDlg->SetSramAddrInfo(sainfo);
    ActionOfMultipleBurnDlgAfterSetSramAddrInfo();
}


void BurnDlgMcu::GetCmdInfoArray(QMap<int, BIN_INFO> &infoArray)
{
    if (binModel == nullptr) {
        return;
    }
    int nRow = binModel->rowCount();
    if (nRow > 0x1000) {
        return;
    }
    infoArray.clear();

    QMap<int, BIN_INFO> binInfo = binModel->GetMapBinFileInfo();
    QMap<int, bool> binCheck = binModel->GetMapCheck();
    int i = 0;
    for (auto it = binInfo.begin(); it != binInfo.end(); it++) {
        if (binCheck[it.key()] && it->type == IMAGE_TYPE::IMAGE_TYPE_LOADER) {
            BIN_INFO_ARRAY infoArrayBin;
            QString version;
            DataConvertor::AnalysMultifBin(ui->lineEditSeleteFile->text(), infoArrayBin, version,
                                           isEncrypt, encryptBuffer);
        }

        if (binCheck[it.key()]) {
            infoArray[i++] = it.value();
        }
    }
}

void BurnDlgMcu::SlotMultipleBurnDlgClose()
{
    if (ui == nullptr) {
        return;
    }
    isMultipleBurnOpen = false;
    ui->btnStartBurn->setEnabled(true);
}

}
